package com.ruoyi.contract.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.contract.domain.*;
import com.ruoyi.contract.domain.contractVo.ContractAllPartyVo;
import com.ruoyi.contract.domain.contractVo.ContractAllPaymentVo;
import com.ruoyi.contract.domain.contractVo.ContractAllRelevantVo;
import com.ruoyi.contract.domain.invoiceVo.SelectInvoiceVo;
import com.ruoyi.contract.mapper.*;
import com.ruoyi.contract.tools.ContractCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.contract.service.IContractService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 合同Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-10-18
 */
@Service
public class ContractServiceImpl implements IContractService 
{
    @Autowired
    private ContractMapper contractMapper;

    @Autowired
    private ContractSigningPartyConnectionMapper contractSigningPartyConnectionMapper;

    @Autowired
    private PaymentCollectionPlanMapper paymentCollectionPlanMapper;

    @Autowired
    private ContractAppendicesMapper contractAppendicesMapper;

    @Autowired
    private InvoiceMapper invoiceMapper;

    @Autowired
    private ContractPartyMapper contractPartyMapper;

    @Autowired
    private BelongingCompanyMapper belongingCompanyMapper;

    @Autowired
    private ContractCategoryMapper contractCategoryMapper;



    /**
     * 查询合同
     * 
     * @param contractId 合同主键
     * @return 合同
     */
    @Override
    public ContractAllRelevantVo selectContractByContractId(Long contractId)
    {
        Contract contract = contractMapper.selectContractByContractId(contractId);
        return buildContractAllRelevantVo(contract);
        //        return contractMapper.selectContractByContractId(contractId);
    }

    /**
     * 查询合同列表
     * 
     * @param contract 合同
     * @return 合同
     */
    @Override
    public List<ContractAllPartyVo> selectContractList(Contract contract)
    {
        List<Contract> contracts = contractMapper.selectContractList(contract);
        List<ContractAllPartyVo> contractAllPartyVos = new ArrayList<>();
        for (Contract contract1: contracts){
            ContractAllPartyVo contractAllPartyVo = new ContractAllPartyVo(contract1);

            // 获取合同签约方列表
            ContractSigningPartyConnection contractSigningPartyConnection = new ContractSigningPartyConnection();
            contractSigningPartyConnection.setContractId(contract1.getContractId());
            List<ContractSigningPartyConnection> contractSigningPartyConnections = contractSigningPartyConnectionMapper.selectContractSigningPartyConnectionList(contractSigningPartyConnection);
            List<String> contractPartyNameList = new ArrayList<>();
            if (contractSigningPartyConnections != null && !contractSigningPartyConnections.isEmpty()) {
                for (ContractSigningPartyConnection connection : contractSigningPartyConnections) {
                    if (connection.getContractPartyName() != null) {
                        contractPartyNameList.add(connection.getContractPartyName());
                    }
                }
            }
            contractAllPartyVo.setContractPartyNameList(contractPartyNameList);
            contractAllPartyVos.add(contractAllPartyVo);
        }
        return contractAllPartyVos;
    }

    /**
     * 新增合同
     * 
     * @param contractAllRelevantVo 合同相关所有数据
     * @return 结果
     */
    @Override
    @Transactional
    public int insertContract(ContractAllRelevantVo contractAllRelevantVo)
    {
        // 新增合同主表
        Contract contract = contractAllRelevantVo.getContract();
        contract.setAddUserId(SecurityUtils.getUserId());
        contract.setAddTime(DateUtils.getNowDate());
        String BelongingCompanyName = belongingCompanyMapper.selectBelongingCompanyByBelongingCompanyId(contract.getBelongingCompanyId()).getName();
        String ContractCategoryNam = contractCategoryMapper.selectContractCategoryByContractCategoryId(contract.getContractCategoryId()).getName();
        if (BelongingCompanyName != null && ContractCategoryNam != null){
            contract.setCode(ContractCode.generateUniqueCode(BelongingCompanyName,ContractCategoryNam));
//            contract.setCode("SD123XM12320241025151636");
        }
        int insert = contractMapper.insertContract(contract);

        //新增收付款计划
        for (PaymentCollectionPlan paymentCollectionPlan: contractAllRelevantVo.getPaymentCollectionPlanList()){
            if (paymentCollectionPlan.getPayableAmount()!=null && paymentCollectionPlan.getState() !=null&& !paymentCollectionPlan.getState().isEmpty()){
                paymentCollectionPlan.setContractId(contract.getContractId());
                paymentCollectionPlanMapper.insertPaymentCollectionPlan(paymentCollectionPlan);
            }
        }

        //新增合同附件列表
        for (ContractAppendices contractAppendices: contractAllRelevantVo.getContractAppendicesList()){
            contractAppendices.setContractId(contract.getContractId());
            contractAppendicesMapper.insertContractAppendices(contractAppendices);
        }

        //签约方不存在时新增签约方，新增签约方连表，修改合同主表的签约方字符串
        String contractPartyString = "";
        List<String> PartyNameList = contractAllRelevantVo.getContractPartyNameList().stream().distinct().collect(Collectors.toList());

        //判断签约方是否填写，未填写则提示
        if(PartyNameList.stream().anyMatch(name -> name == null || name.isEmpty())){
            throw new IllegalArgumentException("请填写签约方");
        }

        for (String contractPartyName : PartyNameList){
            contractPartyString = contractPartyString + contractPartyName + ',';
            ContractParty contractParty = new ContractParty();
            contractParty.setName(contractPartyName);
            if(contractPartyMapper.selectContractPartyInfo(contractParty)== null){//如果签约方不存在就新建签约方
                contractPartyMapper.insertContractParty(contractParty);
            }else{
                contractParty = contractPartyMapper.selectContractPartyInfo(contractParty);
            }
            //新增签约方连表
            ContractSigningPartyConnection contractSigningPartyConnection = new ContractSigningPartyConnection();
            contractSigningPartyConnection.setContractId(contract.getContractId());
            contractSigningPartyConnection.setContractPartyId(contractParty.getContractPartyId());
            contractSigningPartyConnectionMapper.insertContractSigningPartyConnection(contractSigningPartyConnection);
        }

        //修改合同主表的签约方字符串
        if (!contractPartyString.isEmpty()){
            contractPartyString = contractPartyString.substring(0, contractPartyString.length() - 1); // 去掉最后一个逗号
        }
        contract.setPartyString(contractPartyString);
        contractMapper.updateContract(contract);

        //重新计算其中金额、发票总额、合同附件总额、已收（付）款金额，修改收（付）款状态
        ContractAllRelevantVo EndContractAllRelevantVo = buildContractAllRelevantVo(contract);
        contract = EndContractAllRelevantVo.getContract();

        contractMapper.updateContract(contract);

        return insert;
    }

    /**
     * 修改合同
     * 
     * @param contractAllRelevantVo 合同相关所有数据
     * @return 结果
     */
    @Override
    @Transactional
    public int updateContract(ContractAllRelevantVo contractAllRelevantVo)
    {
        //修改合同主表
        Contract contract = contractAllRelevantVo.getContract();
        contract.setUpdateUserId(SecurityUtils.getUserId());
        contract.setUpdateTime(DateUtils.getNowDate());

        //删除所有合同收付款详情,重新新增
        paymentCollectionPlanMapper.deletePaymentCollectionPlanByContractId(contract.getContractId());
        for (PaymentCollectionPlan paymentCollectionPlan: contractAllRelevantVo.getPaymentCollectionPlanList()){
            if (paymentCollectionPlan.getPayableAmount()!=null && paymentCollectionPlan.getState() !=null&& !paymentCollectionPlan.getState().isEmpty()){
                paymentCollectionPlan.setContractId(contract.getContractId());
                paymentCollectionPlanMapper.insertPaymentCollectionPlan(paymentCollectionPlan);
            }
        }

        //删除所有该合同附件，重新添加
        contractAppendicesMapper.deleteContractAppendicesByContractId(contract.getContractId());
        for (ContractAppendices contractAppendices:contractAllRelevantVo.getContractAppendicesList()){
            contractAppendices.setContractId(contract.getContractId());
                contractAppendicesMapper.insertContractAppendices(contractAppendices);
        }

        //删除所有此合同相关签约方，判定签约方是否存在，不存在则添加签约方，重新添加合同签约方连表，并修改合同主表签约方字符串
        contractSigningPartyConnectionMapper.deleteContractSigningPartyConnectionByContractId(contract.getContractId());
        String contractPartyString = "";
        List<String> PartyNameList = contractAllRelevantVo.getContractPartyNameList().stream().distinct().collect(Collectors.toList());

        //判断签约方是否填写，未填写则提示
        if(PartyNameList.stream().anyMatch(name -> name == null || name.isEmpty())){
            throw new IllegalArgumentException("请填写签约方");
        }

        for (String contractPartyName : PartyNameList){
            contractPartyString = contractPartyString + contractPartyName + ',';
            ContractParty contractParty = new ContractParty();
            contractParty.setName(contractPartyName);
            if(contractPartyMapper.selectContractPartyInfo(contractParty)== null){//如果签约方不存在就新建签约方
                contractPartyMapper.insertContractParty(contractParty);
            }else{
                contractParty = contractPartyMapper.selectContractPartyInfo(contractParty);
            }
            //新增签约方连表
            ContractSigningPartyConnection contractSigningPartyConnection = new ContractSigningPartyConnection();
            contractSigningPartyConnection.setContractId(contract.getContractId());
            contractSigningPartyConnection.setContractPartyId(contractParty.getContractPartyId());
            contractSigningPartyConnectionMapper.insertContractSigningPartyConnection(contractSigningPartyConnection);
        }
        //修改合同主表的签约方字符串
        if (!contractPartyString.isEmpty()){
            contractPartyString = contractPartyString.substring(0, contractPartyString.length() - 1); // 去掉最后一个逗号
        }
        contract.setPartyString(contractPartyString);
        contractMapper.updateContract(contract);

        //重新计算其中金额、发票总额、合同附件总额、已收（付）款金额，修改收（付）款状态
        ContractAllRelevantVo EndContractAllRelevantVo = buildContractAllRelevantVo(contract);
        contract = EndContractAllRelevantVo.getContract();


        return contractMapper.updateContract(contract);
    }

    /**
     * 批量删除合同
     * 
     * @param contractIds 需要删除的合同主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteContractByContractIds(Long[] contractIds)
    {
        for (Long contractId : contractIds){
            // 删除相关的签约方连表
            contractSigningPartyConnectionMapper.deleteContractSigningPartyConnectionByContractId(contractId);
            // 删除相关的合同附件
            contractAppendicesMapper.deleteContractAppendicesByContractId(contractId);
            //删除收付款计划列表
            paymentCollectionPlanMapper.deletePaymentCollectionPlanByContractId(contractId);
        }
        return contractMapper.deleteContractByContractIds(contractIds);
    }

    /**
     * 删除合同信息
     * 
     * @param contractId 合同主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteContractByContractId(Long contractId)
    {
        // 删除相关的签约方连表
        contractSigningPartyConnectionMapper.deleteContractSigningPartyConnectionByContractId(contractId);
        // 删除相关的合同附件
        contractAppendicesMapper.deleteContractAppendicesByContractId(contractId);
        //删除收付款计划列表
        paymentCollectionPlanMapper.deletePaymentCollectionPlanByContractId(contractId);

        return contractMapper.deleteContractByContractId(contractId);
    }

    /**
     * 查询所有合同和其收付款计划
     *
     * @return 合同和收付款计划集合
     */
    @Override
    public List<ContractAllPaymentVo> selectContractPaymentList(Contract contract)
    {
        List<ContractAllPaymentVo> contractAllPaymentVos = new ArrayList<>();
        for (Contract contract1 : contractMapper.selectContractList(contract)){
            ContractAllPaymentVo contractAllPaymentVo = new ContractAllPaymentVo();
            //添加合同
            contractAllPaymentVo.setContract(contract1);
            //添加签约方列表
            ContractSigningPartyConnection contractSigningPartyConnection = new ContractSigningPartyConnection();
            contractSigningPartyConnection.setContractId(contract1.getContractId());
            List<ContractSigningPartyConnection> contractSigningPartyConnections = contractSigningPartyConnectionMapper.selectContractSigningPartyConnectionList(contractSigningPartyConnection);
            List<String> contractPartyNameList = new ArrayList<>();
            if (contractSigningPartyConnections != null && !contractSigningPartyConnections.isEmpty()) {
                for (ContractSigningPartyConnection connection : contractSigningPartyConnections) {
                    if (connection.getContractPartyName() != null) {
                        contractPartyNameList.add(connection.getContractPartyName());
                    }
                }
            }
            contractAllPaymentVo.setContractPartyNameList(contractPartyNameList);
            //添加收付款计划列表
            PaymentCollectionPlan paymentCollectionPlan = new PaymentCollectionPlan();
            paymentCollectionPlan.setContractId(contract1.getContractId());
            List<PaymentCollectionPlan> paymentCollectionPlanList = paymentCollectionPlanMapper.selectPaymentCollectionPlanList(paymentCollectionPlan);
            contractAllPaymentVo.setPaymentCollectionPlanVos(paymentCollectionPlanList);

            contractAllPaymentVos.add(contractAllPaymentVo);
        }

        return contractAllPaymentVos;
    }

    /**
     * 查询合同列表
     *
     * @param contractIds 合同主键列表
     * @return 合同集合
     */
    @Override
    public List<Contract> selectContractListByContractIds(Long[] contractIds){
        List<Contract> contractList = new ArrayList<>();
        for(Long contractId : contractIds){
            contractList.add(contractMapper.selectContractByContractId(contractId));
        }
        return contractList;
    }

    private ContractAllRelevantVo buildContractAllRelevantVo(Contract contract) {
        if(contract.getMoney() == null){
            contract.setMoney(new BigDecimal(0));
        }

        ContractAllRelevantVo contractAllRelevantVo = new ContractAllRelevantVo(contract);

        //如果生效日期在终止日期后，抛出异常
        if (contract.getEffectiveTime().compareTo(contract.getTerminationTime()) > 0){
            throw new IllegalArgumentException("合同生效日期应在终止日期之前");
        }
        // 获取合同签约方列表
        ContractSigningPartyConnection contractSigningPartyConnection = new ContractSigningPartyConnection();
        contractSigningPartyConnection.setContractId(contract.getContractId());
        List<ContractSigningPartyConnection> contractSigningPartyConnections = contractSigningPartyConnectionMapper.selectContractSigningPartyConnectionList(contractSigningPartyConnection);
        List<String> contractPartyNameList = new ArrayList<>();
        if (contractSigningPartyConnections != null && !contractSigningPartyConnections.isEmpty()) {
            for (ContractSigningPartyConnection connection : contractSigningPartyConnections) {
                if (connection.getContractPartyName() != null) {
                    contractPartyNameList.add(connection.getContractPartyName());
                }
            }
        }
        contractAllRelevantVo.setContractPartyNameList(contractPartyNameList);

        // 获取收付款计划
        PaymentCollectionPlan paymentCollectionPlan = new PaymentCollectionPlan();
        paymentCollectionPlan.setContractId(contract.getContractId());
        List<PaymentCollectionPlan> paymentCollectionPlanList = paymentCollectionPlanMapper.selectPaymentCollectionPlanList(paymentCollectionPlan);
        contractAllRelevantVo.setPaymentCollectionPlanList(paymentCollectionPlanList != null ? paymentCollectionPlanList : new ArrayList<>());

        // 获取合同附件列表
        ContractAppendices contractAppendices = new ContractAppendices();
        contractAppendices.setContractId(contract.getContractId());
        List<ContractAppendices> contractAppendicesList = contractAppendicesMapper.selectContractAppendicesList(contractAppendices);
        contractAllRelevantVo.setContractAppendicesList(contractAppendicesList != null ? contractAppendicesList : new ArrayList<>());

        // 获取发票列表
        Invoice invoice = new Invoice();
        invoice.setContractCode(contract.getCode());
        List<SelectInvoiceVo> invoiceList = invoiceMapper.selectInvoiceList(invoice);
        contractAllRelevantVo.setSelectInvoiceVo(invoiceList != null ? invoiceList : new ArrayList<>());

        // 计算附件总额
        BigDecimal allAppendicesMoney = new BigDecimal(0);
        for (ContractAppendices contractAppendices1 : contractAllRelevantVo.getContractAppendicesList()) {
            if (contractAppendices1.getMoney()!=null){
                allAppendicesMoney = allAppendicesMoney.add(contractAppendices1.getMoney());
            }
            //如果生效日期在终止日期后，抛出异常
            if(contractAppendices1.getEffectiveTime() !=null && contractAppendices1.getTerminationTime() !=null)
            if (contractAppendices1.getEffectiveTime().compareTo(contractAppendices1.getTerminationTime()) > 0){
                throw new IllegalArgumentException("合同附件生效日期应在合同附件终止日期之前");
            }
        }
        contractAllRelevantVo.getContract().setAllAppendicesMoney(allAppendicesMoney);

        // 计算合同总额
        BigDecimal allMoney = allAppendicesMoney.add(contract.getMoney());
        contractAllRelevantVo.getContract().setAllMoney(allMoney);

        if (allMoney.compareTo(new BigDecimal(0)) ==0 && (contract.getCollectionAndPaymentTypes() !=null && !contract.getCollectionAndPaymentTypes().isEmpty())) {
            throw new IllegalArgumentException("请填写‘合同金额’或‘合同附件金额’");
        }else if (allMoney.compareTo(new BigDecimal(0)) !=0 &&( contract.getCollectionAndPaymentTypes() ==null || contract.getCollectionAndPaymentTypes().isEmpty() )){
            throw new IllegalArgumentException("请填写’收（付）款类型‘");
        }

        // 计算已收(付)金额、应收（付）款金额、发票金额
        BigDecimal allPaidPayment = new BigDecimal(0);
        BigDecimal allShouldPayment = new BigDecimal(0);
        BigDecimal allInvoiceMoney = new BigDecimal(0);
        List<PaymentCollectionPlan> paymentCollectionPlans = contractAllRelevantVo.getPaymentCollectionPlanList();
        for (PaymentCollectionPlan paymentPlan : paymentCollectionPlans) {
            allShouldPayment = allShouldPayment.add(paymentPlan.getPayableAmount());
            allPaidPayment = allPaidPayment.add(paymentPlan.getActualPayableAmount());
            allInvoiceMoney = allInvoiceMoney.add(paymentPlan.getInvoiceAmount());
        }
        contractAllRelevantVo.getContract().setAllInvoiceMoney(allInvoiceMoney);
        contractAllRelevantVo.getContract().setPaidPayment(allPaidPayment);
        //当合同总应收（付）款不等于合同金额，向外抛出异常，并触发事件回滚
        if (allShouldPayment.compareTo(allMoney) !=0 && !paymentCollectionPlans.isEmpty()){
            throw new IllegalArgumentException("应收（付）金额应该等于合同总额");
        }

        //根据其收付款计划详情的收付款状态，来确定合同的收付款状态
        if (!paymentCollectionPlans.isEmpty()) {
            if ("收款".equals(contractAllRelevantVo.getContract().getCollectionAndPaymentTypes())){
                if (paymentCollectionPlans.stream()//若全为已收款
                        .allMatch(paymentCollectionPlan1  -> "已收款".equals(paymentCollectionPlan1.getState()))){
                    contractAllRelevantVo.getContract().setCollectionAndPaymentState("已收款");
                }else if (paymentCollectionPlans.stream()//若全为未收款
                        .allMatch(paymentCollectionPlan1  -> "未收款".equals(paymentCollectionPlan1.getState()))){
                    contractAllRelevantVo.getContract().setCollectionAndPaymentState("未收款");
                }else{
                    contractAllRelevantVo.getContract().setCollectionAndPaymentState("部分收款");
                }
            }else{
                if (paymentCollectionPlans.stream()//若全为已付款
                        .allMatch(paymentCollectionPlan1  -> "已付款".equals(paymentCollectionPlan1.getState()))){
                    contractAllRelevantVo.getContract().setCollectionAndPaymentState("已付款");
                }else if (paymentCollectionPlans.stream()//若全为未付款
                        .allMatch(paymentCollectionPlan1  -> "未付款".equals(paymentCollectionPlan1.getState()))){
                    contractAllRelevantVo.getContract().setCollectionAndPaymentState("未付款");
                }else{
                    contractAllRelevantVo.getContract().setCollectionAndPaymentState("部分付款");
                }
            }
        }else {//若未空
            if (contractAllRelevantVo.getContract().getCollectionAndPaymentTypes() ==null || contractAllRelevantVo.getContract().getCollectionAndPaymentTypes().isEmpty()){//若收付款类型也为空
                contractAllRelevantVo.getContract().setCollectionAndPaymentState("");
            }else if ("收款".equals(contractAllRelevantVo.getContract().getCollectionAndPaymentTypes())){//若收付款类型为收款
                contractAllRelevantVo.getContract().setCollectionAndPaymentState("未收款");
            }else{
                contractAllRelevantVo.getContract().setCollectionAndPaymentState("未付款");//若收付款类型为付款
            }
        }
        return contractAllRelevantVo;
    }

}
